package com.rc.saas.mini.evcharge;


import com.rc.saas.mini.common.utils.SerializeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class RedisDaoImpl implements RedisDao {
    @Autowired
    @Qualifier("redisTemplate2")
    private RedisTemplate redisTemplate2;

    @Override
    public Object getSession(final String keyValue) {
        return redisTemplate2.execute(new RedisCallback<Object>() {

            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                byte[] key = redisTemplate2.getStringSerializer().serialize(keyValue);
                if (connection.exists(key)) {
                    byte[] value = connection.get(key);
                    return SerializeUtil.unserialize(value);
                }
                return null;
            }
        });

    }

    @Override
    public void putSession(final String key, final Object value) {
        redisTemplate2.execute(new RedisCallback<Object>() {
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                connection.set(redisTemplate2.getStringSerializer().serialize(key), SerializeUtil.serialize(value));
                //connection.set(redisTemplate.getStringSerializer().serialize(key), value);
                return null;
            }
        });
    }

    @Override
    public void putListSession(final String key, final Object value) {
        redisTemplate2.opsForList().leftPush(key, value);
    }

    @Override
    public List getListSession(final String keyValue) {
        final Long listSize = redisTemplate2.opsForList().size(keyValue);
        List list = redisTemplate2.opsForList().range(keyValue, 0, listSize);
        return list;
    }

    @Override
    public void popListSession(final String keyValue) {
        final Long listSize = redisTemplate2.opsForList().size(keyValue);
        for (int i = 0; i < listSize; i++) {
            redisTemplate2.opsForList().leftPop(keyValue);
        }
    }

    @Override
    public void setListSession(final String key, final int index, final Object value) {
        redisTemplate2.opsForList().set(key, index, value);
    }

    @Override
    public Long listSessionSize(final String key) {
        return redisTemplate2.opsForList().size(key);
    }

    @Override
    public void removeListSession(final String key, final long index, final Object value) {
        redisTemplate2.opsForList().remove(key, index, value);
    }

    @Override
    public void putHashAllSession(final String key, final Map map) {
        redisTemplate2.opsForHash().putAll(key, map);

    }

    @Override
    public void delHashKeyMap(String key, String keyMap) {
        redisTemplate2.opsForHash().delete(key, keyMap);
    }

    @Override
    public void putHashSession(final String key, final String keyMap, final Object obj) {
        redisTemplate2.opsForHash().put(key, keyMap, obj);
    }

    @Override
    public Map getHashAllSession(final String key) {
        return redisTemplate2.opsForHash().entries(key);
    }

    @Override
    public Object getHashSession(final String key, final String mapKey) {
        return redisTemplate2.opsForHash().get(key, mapKey);
    }

    @Override
    public void deleteSession(final String key) {
        //this.redisTemplate.delete(key);
        redisTemplate2.execute(new RedisCallback<Object>() {
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                connection.del(redisTemplate2.getStringSerializer().serialize(key));
                return null;
            }
        });
    }

    @Override
    public Object keys(final String key) {
        return redisTemplate2.execute(new RedisCallback<Object>() {
            public Object doInRedis(RedisConnection connection) {
                Set<byte[]> set = connection.keys(redisTemplate2.getStringSerializer().serialize(key));
                List<String> list = new ArrayList<>();
                for (byte[] by : set) {
                    list.add((String) redisTemplate2.getStringSerializer().deserialize(by));
                }
                return list;
            }
        });
    }

    @Override
    public void leftPushList(String key, Object value) {
        redisTemplate2.opsForList().leftPush(key, value);
    }

    @Override
    public void rightPushList(String key, Object value) {
        redisTemplate2.opsForList().rightPush(key, value);
    }

    @Override
    public Object rightPopList(String key) {
        return redisTemplate2.opsForList().rightPop(key);
    }

    @Override
    public void rightPopAndLeftPush(String key1, String key2) {
        redisTemplate2.opsForList().rightPopAndLeftPush(key1, key2);
    }

    @Override
    public void putRedis(final String key, final String value) {
        redisTemplate2.execute(new RedisCallback<Object>() {
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                connection.set(redisTemplate2.getStringSerializer().serialize(key), redisTemplate2.getStringSerializer().serialize(value));
                return null;
            }
        });

    }

    @Override
    public String getRedis(final String keyValue) {
        return (String) redisTemplate2.execute(new RedisCallback<Object>() {

            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                byte[] key = redisTemplate2.getStringSerializer().serialize(keyValue);
                if (connection.exists(key)) {
                    byte[] value = connection.get(key);
                    return redisTemplate2.getStringSerializer().deserialize(value);
                }
                return null;
            }
        });
    }

    @Override
    public void addExpire(String key, Integer time, TimeUnit timeUnit) {
        redisTemplate2.expire(key, time, timeUnit);
    }

    @Override
    public void addExpireValue(String key, Object value, Integer time, TimeUnit timeUnit) {
        redisTemplate2.opsForValue().set(key, value, time, timeUnit);
    }

    @Override
    public Object getOpsForRedis(String key) {
        return redisTemplate2.opsForValue().get(key);
    }
}
